/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package plagiadetector.utility;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import plagiadetector.datatype.PANCorpus;

/**
 * This parser is used for parsing PAN 2011 XML file with DOM approach.
 * 
 */
public class PANXMLParser {
    private static DocumentBuilderFactory dbf;
    private static DocumentBuilder db;
    private static PANXMLParser mainparser;
    private static PANCorpus pc;
    private static StringBuilder addrparent;
    
    /**
     * Singleton class
     */
    private PANXMLParser(){
            dbf = DocumentBuilderFactory.newInstance();
            try{     
                db = dbf.newDocumentBuilder();
            }catch(ParserConfigurationException pce){
                System.out.println("Failed to initiate XMLParser.");
                pce.printStackTrace();
            }
            
            pc = new PANCorpus();
            addrparent = new StringBuilder();
    }
    
    private static void initiateParser(){
         if(mainparser == null){
            mainparser = new PANXMLParser();
        }
    }
    public static PANXMLParser getInstance(){
        initiateParser();
        return mainparser;
    }
    
    
    public static int countAllXMLs(String addr){
        int count = 0;
        ArrayList<String> xmls = FileUtils.getFileNames(addr, "*.xml");        
        ArrayList<String> dirs = FileUtils.getSubDirectories(addr);
        
        for(String s : xmls){
           count++;
        }
        
       for(String s : dirs){
           count += countAllXMLs(addr+"\\"+s);
       }
       
       return count;
    }
    
    /**
     * 
     * Parse a PAN 2011 Corpus XML file.
     * @param addr  address of the XML file.
     * @return PANCorpus object if succeed, null if not.
     */
    public static PANCorpus parseXML(String addr){
        initiateParser();
        PANCorpus pc = null;
        File f = new File(addr);
        
        
        addrparent.replace(0, addrparent.length(), "");
        addrparent.append(f.getParent());
        f = null; //release
        
        try {
            //extracting corpus info
            Document dom = db.parse(addr);
            Element docelm = dom.getDocumentElement();
            
            addrparent.append("\\").append(docelm.getAttribute("reference"));
            String authors = null; 
            String language = null;
            String title = null;
            boolean obfuse = false;
            NodeList nl = docelm.getElementsByTagName("feature");
             
            for(int i=0; i<nl.getLength();i++){
                if(((Element)nl.item(i)).getAttribute("name").equals("about")){
                    
                    authors =((Element)nl.item(i)).getAttribute("authors");
                    title =((Element)nl.item(i)).getAttribute("title");
                    language = ((Element)nl.item(i)).getAttribute("lang");
                
                }
                else if(((Element)nl.item(i)).getAttribute("name").toLowerCase().equals("md5hash")){
                    
                    //after getting md5 value, create a new PANCorpus object.
                    //authors, language, and title already initialized in this point.
                    pc = new PANCorpus(addr, addrparent.toString(), authors, language, title,((Element)nl.item(i)).getAttribute("value"));
                }
                else{
                    //pc already initialized through this point.
                    
                    //check whether the case is obfuscated or not.             
                    if(((Element)nl.item(i)).getAttribute("obfuscation") != null){ //artificial plagiarism case
                      obfuse = ((Element)nl.item(i)).getAttribute("obfuscation").equals("none") ? false : true;                   
                    }else{ //translation plagiarism case
                       obfuse = ((Element)nl.item(i)).getAttribute("manual_obfuscation").equals("false") ? false : true;
                    }
                    
                    
                    pc.addPANCase(((Element)nl.item(i)).getAttribute("name"), ((Element)nl.item(i)).getAttribute("type"), obfuse, ((Element)nl.item(i)).getAttribute("this_language"), Integer.parseInt(((Element)nl.item(i)).getAttribute("this_offset")), Integer.parseInt(((Element)nl.item(i)).getAttribute("this_length")));
                }
            }

        } catch (SAXException ex) {
            Logger.getLogger(PANXMLParser.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(PANXMLParser.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return pc;
    }
    
    

}
